package com.shlh.saas.service.twitter.impl;

import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.shlh.saas.entity.facebook.EsFacebookFields;
import com.shlh.saas.entity.facebook.FacebookUserEs;
import com.shlh.saas.entity.twitter.EsTwitterFields;
import com.shlh.saas.entity.twitter.TwitterUserEs;
import com.shlh.saas.es.EsIndexInfo;
import com.shlh.saas.es.EsRestClient;
import com.shlh.saas.es.EsSearchRequest;
import com.shlh.saas.model.dto.TwitterQueryDTO;
import com.shlh.saas.service.twitter.TwitterEsService;

import io.micrometer.common.util.StringUtils;
import lombok.extern.slf4j.Slf4j;

import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.index.query.*;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.Arrays;

/**
 * Twitter Elasticsearch服务实现类
 */
@Service
@Slf4j
public class TwitterEsServiceImpl implements TwitterEsService {

    @Override
    public Page<TwitterUserEs> queryTwitterUserList(TwitterUserEs req) {
        Page<TwitterUserEs> pageResult = new Page<>();
        EsSearchRequest esSearchRequest = createEsSearchRequest(req);
        SearchResponse searchResponse =
                EsRestClient.searchWithTermQuery(getEsIndexInfo(), esSearchRequest);
        List<TwitterUserEs> twitterUserEsList = new LinkedList<>();
        SearchHits searchHits = null;
        if (searchResponse != null) {
            searchHits = searchResponse.getHits();
        }
        if (searchHits == null || searchHits.getHits() == null) {
            pageResult.setTotal(req.getTotal());
            pageResult.setSize(req.getSize());
            pageResult.setRecords(twitterUserEsList);
            return pageResult;
        }

        SearchHit[] hits = searchHits.getHits();
        log.debug("ES查询返回{}条结果", hits.length);

        for (SearchHit hit : hits) {
            TwitterUserEs twitterUserEs = convertResult(hit);
            if (Objects.nonNull(twitterUserEs)) {
                twitterUserEsList.add(twitterUserEs);
                log.debug("转换结果: email={}, name={}, screenName={}",
                        twitterUserEs.getEmail(), twitterUserEs.getName(), twitterUserEs.getScreenName());
            }
        }
        // 当前页码
        pageResult.setCurrent(req.getCurrent());
        // 每页大小
        pageResult.setSize(req.getSize());
        pageResult.setRecords(twitterUserEsList);
        // 总记录数
        pageResult.setTotal(searchHits.getTotalHits().value);
        return pageResult;
    }


    /**
     * 获取ES索引信息
     */
    private EsIndexInfo getEsIndexInfo() {
        EsIndexInfo esIndexInfo = new EsIndexInfo();
        esIndexInfo.setClusterName("my-es");
//        esIndexInfo.setClusterName("elasticsearch");
        esIndexInfo.setIndexName("twitter_users");
        return esIndexInfo;
    }

    /**
     * 从Map直接转换为TwitterUserEs对象（用于Scroll查询）
     */
    private TwitterUserEs convertResultFromMap(Map<String, Object> sourceAsMap) {
        if (CollectionUtils.isEmpty(sourceAsMap)) {
            return null;
        }

        TwitterUserEs result = new TwitterUserEs();

        // 使用安全获取方法，避免空指针
        result.setId(getStringSafely(sourceAsMap, EsTwitterFields.ID));
        result.setSourceId(getStringSafely(sourceAsMap, EsTwitterFields.SOURCE_ID));
        result.setSourceTable(getStringSafely(sourceAsMap, EsTwitterFields.SOURCE_TABLE));
        result.setName(getStringSafely(sourceAsMap, EsTwitterFields.NAME));
        result.setScreenName(getStringSafely(sourceAsMap, EsTwitterFields.SCREEN_NAME));
        result.setEmail(getStringSafely(sourceAsMap, EsTwitterFields.EMAIL));

        // 处理数值字段
        result.setFollowers(getIntegerSafely(sourceAsMap, EsTwitterFields.FOLLOWERS));

        // 处理布尔字段
        result.setValid(getBooleanSafely(sourceAsMap, EsTwitterFields.VALID));

        // 处理日期字段
        result.setCreatedAt(getDateSafely(sourceAsMap, EsTwitterFields.CREATED_AT));
        result.setMigrationTimestamp(getDateSafely(sourceAsMap, EsTwitterFields.MIGRATION_TIMESTAMP));

        log.debug("成功转换Twitter ES记录: sourceId={}, sourceTable={}", result.getSourceId(), result.getSourceTable());

        return result;
    }
    
    /**
     * 转换ES查询结果为TwitterUserEs对象
     */
    private TwitterUserEs convertResult(SearchHit hit) {
        Map<String, Object> sourceAsMap = hit.getSourceAsMap();
        if (CollectionUtils.isEmpty(sourceAsMap)) {
            return null;
        }

        TwitterUserEs result = convertResultFromMap(sourceAsMap);
        
        if (result != null) {
            // 处理评分（只有非Scroll查询才有评分）
            float rawScore = hit.getScore();
            BigDecimal score = BigDecimal.valueOf(rawScore)
                    .multiply(BigDecimal.valueOf(100.00))
                    .setScale(2, RoundingMode.HALF_UP);
            result.setScore(score);
        }

        // 设置文档ID
        result.setDocId(hit.getId());

        log.info("转换结果: {}", result.toString());
        return result;
    }

    /**
     * 安全获取字符串值
     */
    private String getStringSafely(Map<String, Object> map, String key) {
        if (map == null || key == null) return null;
        Object value = map.get(key);
        return (value != null) ? value.toString() : null;
    }

    /**
     * 安全获取整数值
     */
    private Integer getIntegerSafely(Map<String, Object> map, String key) {
        if (map == null || key == null) return null;
        Object value = map.get(key);
        if (value == null) return null;

        try {
            if (value instanceof Number) {
                return ((Number) value).intValue();
            }
            return Integer.parseInt(value.toString());
        } catch (NumberFormatException e) {
            log.warn("无法转换为整数: key={}, value={}", key, value);
            return null;
        }
    }

    /**
     * 安全获取布尔值
     */
    private Boolean getBooleanSafely(Map<String, Object> map, String key) {
        if (map == null || key == null) return null;
        Object value = map.get(key);
        if (value == null) return null;

        if (value instanceof Boolean) {
            return (Boolean) value;
        }

        String strValue = value.toString().toLowerCase();
        return "true".equals(strValue) || "1".equals(strValue);
    }

    /**
     * 安全获取日期值
     */
    private Date getDateSafely(Map<String, Object> map, String key) {
        if (map == null || key == null) {
            return null;
        }

        Object value = map.get(key);
        if (value == null) {
            return null;
        }

        try {
            if (value instanceof Date) {
                return (Date) value;
            } else if (value instanceof String) {
                // 使用匹配ES格式的解析器
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                return sdf.parse((String) value);
            } else if (value instanceof Long) {
                // 处理时间戳格式
                return new Date((Long) value);
            }
        } catch (Exception e) {
            // 添加详细错误日志
            log.error("解析日期字段 [{}] 失败. 原始值: [{}]. 错误: {}",
                    key, value, e.getMessage());
        }
        return null;
    }

    /**
     * 创建ES搜索请求
     */
    private EsSearchRequest createEsSearchRequest(TwitterUserEs twitterUserEs) {
        log.debug("创建ES查询请求: contactMethod={}, name={}, screenName={}, email={}",
                twitterUserEs.getContactMethod(), twitterUserEs.getName(),
                twitterUserEs.getScreenName(), twitterUserEs.getEmail());

        EsSearchRequest esSearchRequest = new EsSearchRequest();
        BoolQueryBuilder bq = new BoolQueryBuilder();

        // 姓名查询
        if (twitterUserEs.getName() != null && !twitterUserEs.getName().isEmpty()) {
            MatchQueryBuilder nameQueryBuilder =
                    QueryBuilders.matchQuery(EsTwitterFields.NAME, twitterUserEs.getName());
            nameQueryBuilder.boost(2); // 姓名权重较高
            bq.must(nameQueryBuilder);
        }

        // 屏幕名称查询
        if (twitterUserEs.getScreenName() != null && !twitterUserEs.getScreenName().isEmpty()) {
            MatchQueryBuilder screenNameQueryBuilder =
                    QueryBuilders.matchQuery(EsTwitterFields.SCREEN_NAME, twitterUserEs.getScreenName());
            screenNameQueryBuilder.boost(3); // 屏幕名称权重最高
            bq.must(screenNameQueryBuilder);
        }

        // 邮箱查询
        if (twitterUserEs.getEmail() != null && !twitterUserEs.getEmail().isEmpty()) {
            TermQueryBuilder emailQueryBuilder =
                    QueryBuilders.termQuery(EsTwitterFields.EMAIL, twitterUserEs.getEmail().toLowerCase());
            bq.must(emailQueryBuilder);
        }

        // 粉丝数量范围查询
        if (twitterUserEs.getMinFollowers() != null || twitterUserEs.getMaxFollowers() != null) {
            try {
                RangeQueryBuilder followersRangeQuery = QueryBuilders.rangeQuery(EsTwitterFields.FOLLOWERS);

                if (twitterUserEs.getMinFollowers() != null) {
                    followersRangeQuery.gte(twitterUserEs.getMinFollowers());
                    log.debug("添加粉丝数量最小值查询: followers >= {}", twitterUserEs.getMinFollowers());
                }

                if (twitterUserEs.getMaxFollowers() != null) {
                    followersRangeQuery.lte(twitterUserEs.getMaxFollowers());
                    log.debug("添加粉丝数量最大值查询: followers <= {}", twitterUserEs.getMaxFollowers());
                }

                // 验证范围有效性
                if (twitterUserEs.getMinFollowers() != null && twitterUserEs.getMaxFollowers() != null) {
                    if (twitterUserEs.getMinFollowers() > twitterUserEs.getMaxFollowers()) {
                        log.warn("粉丝数量范围无效: min({}) > max({})",
                                twitterUserEs.getMinFollowers(), twitterUserEs.getMaxFollowers());
                    }
                }


                bq.must(followersRangeQuery);
            } catch (Exception e) {
                log.error("处理粉丝数量范围查询失败: minFollowers={}, maxFollowers={}, error={}",
                        twitterUserEs.getMinFollowers(), twitterUserEs.getMaxFollowers(), e.getMessage());
            }
        }

        if (twitterUserEs.getCreatedYear() != null && !twitterUserEs.getCreatedYear().isEmpty()) {
            BoolQueryBuilder yearBoolQuery = QueryBuilders.boolQuery();

            // 修正年份筛选逻辑：对于多个年份，应该使用 OR 逻辑，而不是范围查询
            for (Integer year : twitterUserEs.getCreatedYear()) {
                // 将年份转为日期范围
                String startDate = year + "-01-01 00:00:00";
                String endDate = year + "-12-31 23:59:59";

                RangeQueryBuilder yearRange = QueryBuilders
                        .rangeQuery(EsTwitterFields.CREATED_AT)
                        .gte(startDate)
                        .lte(endDate);

                yearBoolQuery.should(yearRange); // 任意年份匹配即可
                log.debug("添加年份筛选条件: year={}, startDate={}, endDate={}", year, startDate, endDate);
            }

            bq.must(yearBoolQuery);
            log.debug("添加创建年份筛选查询: years={}", twitterUserEs.getCreatedYear());
        }

        // 数据有效性筛选（默认只查询有效数据）
        bq.must(QueryBuilders.termQuery(EsTwitterFields.VALID, true));

        long currentPage = Math.max(twitterUserEs.getCurrent(), 1);  // 页码至少为1
        long pageSize = twitterUserEs.getSize() > 0 ? twitterUserEs.getSize() : 10;  // 默认每页10条

        long from = (currentPage - 1) * pageSize;

        esSearchRequest.setBq(bq);
        esSearchRequest.setFields(EsTwitterFields.FIELD_QUERY);
        esSearchRequest.setFrom(from);
        esSearchRequest.setSize(twitterUserEs.getSize());
        esSearchRequest.setNeedScroll(false);

        // 添加一致的排序规则，确保分页查询和导出查询结果顺序一致
        // 优先按照 followers 降序排序，保证数据顺序的一致性
        esSearchRequest.setSortName(EsTwitterFields.FOLLOWERS);
        esSearchRequest.setSortOrder("desc");

        log.debug("最终ES查询条件: {}, from={}, size={}, sort={}:{}", bq.toString(), from, twitterUserEs.getSize(),
                EsTwitterFields.FOLLOWERS, "desc");
        return esSearchRequest;
    }


    @Override
    public List<Map<String, Object>> searchByNameAndScreenName(String name, String screenName, int limit) {
        log.info("ES两阶段查询 - 姓名+屏幕名称: name={}, screenName={}, limit={}",
                name, screenName, limit);

        try {
            BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();

            // 姓名匹配（必须条件）
            if (name != null && !name.trim().isEmpty()) {
                boolQuery.must(QueryBuilders.matchQuery(EsTwitterFields.NAME + ".keyword", name));
            }

            // 屏幕名称匹配（必须条件）
            if (screenName != null && !screenName.trim().isEmpty()) {
                boolQuery.must(QueryBuilders.termQuery(EsTwitterFields.SCREEN_NAME, screenName));
            }

            // 数据有效性筛选
            boolQuery.must(QueryBuilders.termQuery(EsTwitterFields.VALID, true));

            return executeEsSearch(boolQuery, Math.min(limit, 50), 0);

        } catch (Exception e) {
            log.error("ES查询失败 - 姓名+屏幕名称: name={}, screenName={}, error={}",
                    name, screenName, e.getMessage(), e);
            return new ArrayList<>();
        }
    }

    @Override
    public List<Map<String, String>> searchByNameAndEmail(String name, String email, int limit) {
        log.info("ES两阶段查询 - 姓名+邮箱: name={}, email={}, limit={}",
                name, email, limit);

        try {
            BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();

            // 姓名匹配（必须条件）
            if (name != null && !name.trim().isEmpty()) {
                boolQuery.must(QueryBuilders.matchQuery(EsTwitterFields.NAME, name));
            }

            // 邮箱匹配（必须条件）
            if (email != null && !email.trim().isEmpty()) {
                boolQuery.must(QueryBuilders.termQuery(EsTwitterFields.EMAIL, email.toLowerCase()));
            }

            // 数据有效性筛选
            boolQuery.must(QueryBuilders.termQuery(EsTwitterFields.VALID, true));

            return executeEsSearchForIdentifiers(boolQuery, Math.min(limit, 50), 0);

        } catch (Exception e) {
            log.error("ES查询失败 - 姓名+邮箱: name={}, email={}, error={}",
                    name, email, e.getMessage(), e);
            return new ArrayList<>();
        }
    }

    @Override
    public List<Map<String, String>> searchByScreenNameAndEmail(String screenName, String email, int limit) {
        log.info("ES两阶段查询 - 屏幕名称+邮箱: screenName={}, email={}, limit={}",
                screenName, email, limit);

        try {
            BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();

            // 屏幕名称匹配（必须条件）
            if (screenName != null && !screenName.trim().isEmpty()) {
                boolQuery.must(QueryBuilders.termQuery(EsTwitterFields.SCREEN_NAME, screenName.toLowerCase()));
            }

            // 邮箱匹配（必须条件）
            if (email != null && !email.trim().isEmpty()) {
                boolQuery.must(QueryBuilders.termQuery(EsTwitterFields.EMAIL, email.toLowerCase()));
            }

            // 数据有效性筛选
            boolQuery.must(QueryBuilders.termQuery(EsTwitterFields.VALID, true));

            return executeEsSearchForIdentifiers(boolQuery, Math.min(limit, 50), 0);

        } catch (Exception e) {
            log.error("ES查询失败 - 屏幕名称+邮箱: screenName={}, email={}, error={}",
                    screenName, email, e.getMessage(), e);
            return new ArrayList<>();
        }
    }

    @Override
    public List<Map<String, String>> searchByEmail(String email, int size, int offset) {
        log.info("ES两阶段查询 - 邮箱精确匹配: email={}, size={}, offset={}", email, size, offset);

        try {
            BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();

            // 邮箱精确匹配（必须条件）
            if (email != null && !email.trim().isEmpty()) {
                boolQuery.must(QueryBuilders.termQuery(EsTwitterFields.EMAIL, email.toLowerCase()));
            }

            // 数据有效性筛选
            boolQuery.must(QueryBuilders.termQuery(EsTwitterFields.VALID, true));

            return executeEsSearchForIdentifiers(boolQuery, Math.min(size, 50), offset);

        } catch (Exception e) {
            log.error("ES查询失败 - 邮箱精确匹配: email={}, error={}", email, e.getMessage(), e);
            return new ArrayList<>();
        }
    }

    @Override
    public List<Map<String, String>> searchByScreenName(String screenName, int limit) {
        log.info("ES两阶段查询 - 屏幕名称精确匹配: screenName={}, limit={}", screenName, limit);

        try {
            BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();

            // 屏幕名称精确匹配（必须条件）
            if (screenName != null && !screenName.trim().isEmpty()) {
                boolQuery.must(QueryBuilders.termQuery(EsTwitterFields.SCREEN_NAME, screenName.toLowerCase()));
            }

            // 数据有效性筛选
            boolQuery.must(QueryBuilders.termQuery(EsTwitterFields.VALID, true));

            return executeEsSearchForIdentifiers(boolQuery, Math.min(limit, 50), 0);

        } catch (Exception e) {
            log.error("ES查询失败 - 屏幕名称精确匹配: screenName={}, error={}", screenName, e.getMessage(), e);
            return new ArrayList<>();
        }
    }

    @Override
    public List<Map<String, String>> searchByFollowersRange(Integer minFollowers, Integer maxFollowers, int limit) {
        log.info("ES两阶段查询 - 粉丝数量范围: minFollowers={}, maxFollowers={}, limit={}",
                minFollowers, maxFollowers, limit);

        try {
            BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();

            // 粉丝数量范围查询
            if (minFollowers != null || maxFollowers != null) {
                // 验证范围有效性
                if (minFollowers != null && maxFollowers != null && minFollowers > maxFollowers) {
                    log.warn("粉丝数量范围无效: min({}) > max({}), 交换数值", minFollowers, maxFollowers);
                    // 交换数值以确保范围有效
                    Integer temp = minFollowers;
                    minFollowers = maxFollowers;
                    maxFollowers = temp;
                }

                RangeQueryBuilder followersRangeQuery = QueryBuilders.rangeQuery(EsTwitterFields.FOLLOWERS);

                if (minFollowers != null) {
                    followersRangeQuery.gte(minFollowers);
                    log.debug("添加粉丝数量最小值查询: followers >= {}", minFollowers);
                }

                if (maxFollowers != null) {
                    followersRangeQuery.lte(maxFollowers);
                    log.debug("添加粉丝数量最大值查询: followers <= {}", maxFollowers);
                }

                boolQuery.must(followersRangeQuery);
            } else {
                log.warn("粉丝数量范围查询参数为空，跳过该查询条件");
            }

            // 数据有效性筛选
            boolQuery.must(QueryBuilders.termQuery(EsTwitterFields.VALID, true));

            return executeEsSearchForIdentifiers(boolQuery, Math.min(limit, 50), 0);

        } catch (Exception e) {
            log.error("ES查询失败 - 粉丝数量范围: minFollowers={}, maxFollowers={}, error={}",
                    minFollowers, maxFollowers, e.getMessage(), e);
            return new ArrayList<>();
        }
    }

    // ==================== 导出功能两阶段查询实现 ====================

    @Override
    public List<Map<String, String>> searchForExport(TwitterQueryDTO queryDTO, int limit) {
        log.info("ES两阶段查询 - 导出数据: queryDTO={}, limit={}", queryDTO, limit);

        try {
            BoolQueryBuilder boolQuery = buildExportQuery(queryDTO);
            return executeEsSearchForIdentifiers(boolQuery, Math.min(limit, 1000000), 0); // 导出支持更大的限制

        } catch (Exception e) {
            log.error("ES导出查询失败: queryDTO={}, error={}", queryDTO, e.getMessage(), e);
            return new ArrayList<>();
        }
    }

    @Override
    public List<Map<String, String>> searchForExportWithPagination(TwitterQueryDTO queryDTO, int from, int size) {
        log.info("ES两阶段查询 - 分页导出数据: queryDTO={}, from={}, size={}", queryDTO, from, size);

        try {
            BoolQueryBuilder boolQuery = buildExportQuery(queryDTO);
            return executeEsSearchForIdentifiersWithPagination(boolQuery, from, size);

        } catch (Exception e) {
            log.error("ES分页导出查询失败: queryDTO={}, from={}, size={}, error={}", queryDTO, from, size, e.getMessage(), e);
            return new ArrayList<>();
        }
    }

    @Override
    public long countForExport(TwitterQueryDTO queryDTO) {
        log.info("ES查询计数 - 导出数据: queryDTO={}", queryDTO);

        try {
            BoolQueryBuilder boolQuery = buildExportQuery(queryDTO);
            return executeEsCountQuery(boolQuery);

        } catch (Exception e) {
            log.error("ES计数查询失败: queryDTO={}, error={}", queryDTO, e.getMessage(), e);
            return 0;
        }
    }

    @Override
    public List<TwitterUserEs> searchTwitterUsersWithEmail(String searchKeyword, int offset, int size) {
        log.info("TwitterES查询Email数据，参数： searchKeyWord={}，offset={}，size={}", searchKeyword, offset, size);

        TwitterUserEs twitterUserEs = new TwitterUserEs();

        twitterUserEs.setName(searchKeyword);
        twitterUserEs.setScreenName(searchKeyword);
        twitterUserEs.setContactMethod("email");

        // 构造查询请求
        BoolQueryBuilder bq = getBq(twitterUserEs);

        EsSearchRequest esSearchRequest = new EsSearchRequest();
        esSearchRequest.setBq(bq);
        esSearchRequest.setFields(EsTwitterFields.FIELD_QUERY);
        esSearchRequest.setFrom((long)offset);
        esSearchRequest.setSize((long) size);
        esSearchRequest.setNeedScroll(false);

        SearchResponse searchResponse =
                EsRestClient.searchWithTermQuery(getEsIndexInfo(), esSearchRequest);

        List<TwitterUserEs> twitterUserEsList = new LinkedList<>();
        SearchHits searchHits = null;
        if (searchResponse != null) {
            searchHits = searchResponse.getHits();
        }
        if (searchHits == null || searchHits.getHits() == null) {
            return twitterUserEsList;
        }

        SearchHit[] hits = searchHits.getHits();

        for (SearchHit hit : hits) {
            twitterUserEs = convertResult(hit);
            if (Objects.nonNull(twitterUserEs)) {
                twitterUserEsList.add(twitterUserEs);
            } else {
                log.warn("🔍 ES查询调试 - 数据转换失败: hitId={}", hit.getId());
            }
        }
        return twitterUserEsList;
    }

    @Override
    public Long countTwitterUsersWithEmail(String searchKeyword) {
        log.info("TwitterES查询Email数据量，参数： searchKeyWord={}", searchKeyword);

        TwitterUserEs twitterUserEs = new TwitterUserEs();

        twitterUserEs.setName(searchKeyword);
        twitterUserEs.setScreenName(searchKeyword);
        twitterUserEs.setContactMethod("email");

        BoolQueryBuilder bq = getBq(twitterUserEs);

        // 构造查询请求
        EsSearchRequest esSearchRequest = new EsSearchRequest();
        esSearchRequest.setBq(bq);
        esSearchRequest.setFrom(0L);
        esSearchRequest.setSize(0L);
        esSearchRequest.setNeedScroll(false);
        esSearchRequest.setTrackTotalHits(true);

        SearchResponse searchResponse =
                EsRestClient.searchWithTermQuery(getEsIndexInfo(), esSearchRequest);

        if (searchResponse == null) {
            log.warn("TwitterUsersES计数查询返回null响应");
            return 0L;
        }

        SearchHits searchHits = searchResponse.getHits();
        if (searchHits == null) {
            log.warn("TwitterUsersES计数查询返回空结果");
            return 0L;
        }

        long totalCount = 0L;
        if (searchHits.getTotalHits() != null) {
            totalCount = searchHits.getTotalHits().value;
        }
        log.info("TwitterUsersES计数查询完成，匹配记录总数: {}", totalCount);

        return totalCount;
    }

    @Override
    public List<Map<String, String>> searchByKeyWord(String keyword, int offset, int limit) {
        try {
            TwitterUserEs twitterUserEs = new TwitterUserEs();

            twitterUserEs.setName(keyword);
            twitterUserEs.setScreenName(keyword);

            BoolQueryBuilder boolQuery = getShouldBq(twitterUserEs);

            return executeEsSearchForIdentifiers(boolQuery, limit, offset);
        } catch (Exception e) {
            log.error("ES查询失败 - 关键字搜索: keyword={}, error={}", keyword, e.getMessage(), e);
            return new ArrayList<>();
        }
    }

    @Override
    public List<Map<String, Object>> findByKeyWord(String keyword, int offset, int limit) {
        try {
            TwitterUserEs twitterUserEs = new TwitterUserEs();

            twitterUserEs.setName(keyword);
            twitterUserEs.setScreenName(keyword);

            BoolQueryBuilder boolQuery = getShouldBq(twitterUserEs);

            return executeEsSearch(boolQuery, limit, offset);
        } catch (Exception e) {
            log.error("ES查询失败 - 关键字搜索: keyword={}, error={}", keyword, e.getMessage(), e);
            return new ArrayList<>();
        }
    }



    @Override
    public long countTwitterUsersWithKeyWord(String keyword) {
        TwitterUserEs twitterUserEs = new TwitterUserEs();

        twitterUserEs.setName(keyword);
        twitterUserEs.setScreenName(keyword);

        BoolQueryBuilder shouldBq = getShouldBq(twitterUserEs);

        return executeEsCountQuery(shouldBq);
    }

    @Override
    public List<TwitterUserEs> searchTwitterDataWithEmail(String companyName, String fullName) {
        log.info("TwitterES查询Email数据，参数： companyName={}，fullName={}", companyName, fullName);

        TwitterUserEs twitterUserEs = new TwitterUserEs();

        twitterUserEs.setName(fullName);
//        twitterUserEs.setScreenName(fullName);
        twitterUserEs.setContactMethod("email");

        // 构造查询请求
        BoolQueryBuilder bq = getBq(twitterUserEs);

        EsSearchRequest esSearchRequest = new EsSearchRequest();
        esSearchRequest.setBq(bq);
        esSearchRequest.setFields(EsTwitterFields.FIELD_QUERY);
        
        // 使用普通分页查询，限制最多返回5000条，避免查询过多数据
        esSearchRequest.setNeedScroll(false); // 不使用Scroll，使用普通查询
        esSearchRequest.setFrom(0L); // 设置起始位置
        esSearchRequest.setSize(5000L); // 最多返回5000条记录

        log.info("执行Twitter ES查询，限制最多返回5000条结果");

        // 使用普通查询而非scroll查询
        SearchResponse searchResponse = EsRestClient.searchWithTermQuery(getEsIndexInfo(), esSearchRequest);
        
        List<TwitterUserEs> twitterUserEsList = new LinkedList<>();
        if (searchResponse != null && searchResponse.getHits() != null) {
            SearchHits hits = searchResponse.getHits();
            log.info("Twitter ES查询完成，共找到{}条匹配数据", hits.getTotalHits().value);
            
            for (SearchHit hit : hits.getHits()) {
                TwitterUserEs user = convertResultFromMap(hit.getSourceAsMap());
                if (user != null) {
                    twitterUserEsList.add(user);
                }
            }
        }
        
        log.info("Twitter ES查询返回{}条数据", twitterUserEsList.size());
        return twitterUserEsList;
    }

    private BoolQueryBuilder getShouldBq(TwitterUserEs twitterUserEs) {
        BoolQueryBuilder bq = new BoolQueryBuilder();

        // 姓名查询
        if (twitterUserEs.getName() != null && !twitterUserEs.getName().isEmpty()) {
            TermQueryBuilder nameQueryBuilder =
                    QueryBuilders.termQuery(EsTwitterFields.NAME + ".keyword", twitterUserEs.getName());
            nameQueryBuilder.boost(2); // 姓名权重较高
            bq.should(nameQueryBuilder);
        }

        // 屏幕名称查询
        if (twitterUserEs.getScreenName() != null && !twitterUserEs.getScreenName().isEmpty()) {
            TermQueryBuilder screenNameQueryBuilder =
                    QueryBuilders.termQuery(EsTwitterFields.SCREEN_NAME, twitterUserEs.getScreenName());
            screenNameQueryBuilder.boost(3); // 屏幕名称权重最高
            bq.should(screenNameQueryBuilder);
        }

        return bq;
    }

    private BoolQueryBuilder getBq(TwitterUserEs twitterUserEs) {
        BoolQueryBuilder bq = new BoolQueryBuilder();

        // 姓名条件构建 - 使用match_phrase或AND操作符，提高精确度
        BoolQueryBuilder nameQuery = QueryBuilders.boolQuery();
        boolean hasNameCondition = false;

        if (StringUtils.isNotBlank(twitterUserEs.getName())) {
            // 使用match_phrase进行短语匹配，更精确
            nameQuery.should(QueryBuilders.matchPhraseQuery(EsTwitterFields.NAME, twitterUserEs.getName()).boost(3.0f));
            // 同时添加match query with AND operator作为备选
            nameQuery.should(QueryBuilders.matchQuery(EsTwitterFields.NAME, twitterUserEs.getName())
                    .operator(Operator.AND).boost(2.0f));
            hasNameCondition = true;
        }

        if (StringUtils.isNotBlank(twitterUserEs.getScreenName())) {
            // screen_name也使用match_phrase
            nameQuery.should(QueryBuilders.matchPhraseQuery(EsTwitterFields.SCREEN_NAME, twitterUserEs.getScreenName()).boost(2.0f));
            nameQuery.should(QueryBuilders.matchQuery(EsTwitterFields.SCREEN_NAME, twitterUserEs.getScreenName())
                    .operator(Operator.AND).boost(1.5f));
            hasNameCondition = true;
        }

        // 只有存在姓名条件时才添加到主查询
        if (hasNameCondition) {
            nameQuery.minimumShouldMatch(1);  // 至少匹配一个条件
            bq.must(nameQuery);
        }

        // 邮箱查询条件 - 确保email字段不为空
        if ("email".equals(twitterUserEs.getContactMethod())) {
            BoolQueryBuilder emailQuery = QueryBuilders.boolQuery()
                    .must(QueryBuilders.existsQuery(EsTwitterFields.EMAIL))
                    .mustNot(QueryBuilders.termQuery(EsTwitterFields.EMAIL, ""))
                    .must(QueryBuilders.wildcardQuery(EsTwitterFields.EMAIL, "*@*"));
            bq.must(emailQuery);
        }

        log.debug("构建的查询条件: {}", bq);
        return bq;
    }

    /**
     * 构建导出查询的ES查询条件
     *
     * @param queryDTO 查询条件DTO
     * @return BoolQueryBuilder
     */
    private BoolQueryBuilder buildExportQuery(TwitterQueryDTO queryDTO) {
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();

        // 姓名查询
        if (queryDTO.getName() != null && !queryDTO.getName().trim().isEmpty()) {
            boolQuery.must(QueryBuilders.matchQuery(EsTwitterFields.NAME, queryDTO.getName()));
        }

        // 屏幕名称查询
        if (queryDTO.getScreenName() != null && !queryDTO.getScreenName().trim().isEmpty()) {
            boolQuery.must(QueryBuilders.termQuery(EsTwitterFields.SCREEN_NAME, queryDTO.getScreenName().toLowerCase()));
        }

        // 邮箱查询
        if (queryDTO.getEmail() != null && !queryDTO.getEmail().trim().isEmpty()) {
            boolQuery.must(QueryBuilders.termQuery(EsTwitterFields.EMAIL, queryDTO.getEmail().toLowerCase()));
        }

        // 粉丝数量范围查询
        if (queryDTO.getFollowers_range() != null && queryDTO.getFollowers_range().length >= 2) {
            try {
                Integer minFollowers = queryDTO.getFollowers_range()[0];
                Integer maxFollowers = queryDTO.getFollowers_range()[1];

                // 验证数值有效性
                if (minFollowers != null && maxFollowers != null && minFollowers <= maxFollowers) {
                    RangeQueryBuilder followersRangeQuery = QueryBuilders.rangeQuery(EsTwitterFields.FOLLOWERS);
                    followersRangeQuery.gte(minFollowers);
                    followersRangeQuery.lte(maxFollowers);
                    boolQuery.must(followersRangeQuery);

                    log.debug("添加粉丝数量范围查询: {} <= followers <= {}", minFollowers, maxFollowers);
                } else {
                    log.warn("粉丝数量范围无效: minFollowers={}, maxFollowers={}", minFollowers, maxFollowers);
                }
            } catch (Exception e) {
                log.error("处理粉丝数量范围查询失败: followers={}, error={}",
                        Arrays.toString(queryDTO.getFollowers_range()), e.getMessage());
            }
        } else if (queryDTO.getFollowers_range() != null && queryDTO.getFollowers_range().length > 0) {
            log.warn("粉丝数量数组长度不足，需要至少2个元素: length={}", queryDTO.getFollowers_range().length);
        }

        // 注册年份筛选
        if (queryDTO.getCreated_at_year() != null && !queryDTO.getCreated_at_year().isEmpty()) {
            BoolQueryBuilder yearBoolQuery = QueryBuilders.boolQuery();

            // 对于多个年份，使用 OR 逻辑
            for (Integer year : queryDTO.getCreated_at_year()) {
                // 将年份转为日期范围
                String startDate = year + "-01-01 00:00:00";
                String endDate = year + "-12-31 23:59:59";

                RangeQueryBuilder yearRange = QueryBuilders
                        .rangeQuery(EsTwitterFields.CREATED_AT)
                        .gte(startDate)
                        .lte(endDate);

                yearBoolQuery.should(yearRange); // 任意年份匹配即可
                log.debug("添加导出年份筛选条件: year={}, startDate={}, endDate={}", year, startDate, endDate);
            }

            boolQuery.must(yearBoolQuery);
            log.debug("添加导出创建年份筛选查询: years={}", queryDTO.getCreated_at_year());
        }

        // 联系方式筛选
        if (queryDTO.getContactMethod() != null &&
                !queryDTO.getContactMethod().trim().isEmpty() &&
                !queryDTO.getContactMethod().equals("any")) {

            String contactMethod = queryDTO.getContactMethod();
            log.debug("处理联系方式筛选: {}", contactMethod);

            if (contactMethod.equals("email")) {
                // 检查email字段存在且不为空，并且包含@符号
                BoolQueryBuilder emailQuery = QueryBuilders.boolQuery()
                        .must(QueryBuilders.existsQuery(EsTwitterFields.EMAIL))
                        .mustNot(QueryBuilders.termQuery(EsTwitterFields.EMAIL, ""))
                        .must(QueryBuilders.wildcardQuery(EsTwitterFields.EMAIL, "*@*"));
                boolQuery.must(emailQuery);
            }
        }

        // 数据有效性筛选（默认只查询有效数据）
        boolQuery.must(QueryBuilders.termQuery(EsTwitterFields.VALID, true));

        log.debug("构建导出查询条件: {}", boolQuery.toString());
        return boolQuery;
    }

    private List<Map<String, Object>> executeEsSearch(BoolQueryBuilder boolQuery, int limit, int offset) {
        List<Map<String, Object>> results = new ArrayList<>();

        try {
            // 创建ES搜索请求
            EsSearchRequest esSearchRequest = new EsSearchRequest();
            esSearchRequest.setBq(boolQuery);
            esSearchRequest.setFrom((long) offset);
            esSearchRequest.setSize((long) limit);
            esSearchRequest.setNeedScroll(false);

            // 添加排序规则，确保与分页查询一致
            esSearchRequest.setSortName(EsTwitterFields.FOLLOWERS);
            esSearchRequest.setSortOrder("desc");

            // 只查询必要的字段以提升性能
            esSearchRequest.setFields(EsTwitterFields.FIELD_QUERY);

            log.debug("执行ES查询，条件: {}, limit: {}, sort: {}:{}", boolQuery.toString(), limit,
                    EsTwitterFields.FOLLOWERS, "desc");

            // 执行查询
            SearchResponse searchResponse = EsRestClient.searchWithTermQuery(getEsIndexInfo(), esSearchRequest);

            if (searchResponse == null) {
                log.warn("ES查询返回null响应");
                return results;
            }

            SearchHits searchHits = searchResponse.getHits();
            if (searchHits == null || searchHits.getHits() == null) {
                log.warn("ES查询返回空结果");
                return results;
            }

            SearchHit[] hits = searchHits.getHits();
            log.info("ES查询返回{}条匹配记录", hits.length);

            // 提取标识信息
            for (SearchHit hit : hits) {
                Map<String, Object> sourceAsMap = hit.getSourceAsMap();
                results.add(sourceAsMap);
            }

            log.info("ES查询完成，有效匹配记录数: {}", results.size());
            return results;

        } catch (Exception e) {
            log.error("执行ES查询失败: {}", e.getMessage(), e);
            return results;
        }

    }

    /**
     * 执行ES查询并返回标识信息
     *
     * @param boolQuery 布尔查询条件
     * @param limit     最大返回数量
     * @return 包含sourceTable和sourceId的结果列表
     */
    private List<Map<String, String>> executeEsSearchForIdentifiers(BoolQueryBuilder boolQuery, int limit, int offset) {
        List<Map<String, String>> results = new ArrayList<>();

        try {
            // 创建ES搜索请求
            EsSearchRequest esSearchRequest = new EsSearchRequest();
            esSearchRequest.setBq(boolQuery);
            esSearchRequest.setFrom((long) offset);
            esSearchRequest.setSize((long) limit);
            esSearchRequest.setNeedScroll(false);

            // 添加排序规则，确保与分页查询一致
            esSearchRequest.setSortName(EsTwitterFields.FOLLOWERS);
            esSearchRequest.setSortOrder("desc");

            // 只查询必要的字段以提升性能
            String[] fields = {EsTwitterFields.SOURCE_TABLE, EsTwitterFields.SOURCE_ID};
            esSearchRequest.setFields(fields);

            log.debug("执行ES查询，条件: {}, limit: {}, sort: {}:{}", boolQuery.toString(), limit,
                    EsTwitterFields.FOLLOWERS, "desc");

            // 执行查询
            SearchResponse searchResponse = EsRestClient.searchWithTermQuery(getEsIndexInfo(), esSearchRequest);

            if (searchResponse == null) {
                log.warn("ES查询返回null响应");
                return results;
            }

            SearchHits searchHits = searchResponse.getHits();
            if (searchHits == null || searchHits.getHits() == null) {
                log.warn("ES查询返回空结果");
                return results;
            }

            SearchHit[] hits = searchHits.getHits();
            log.info("ES查询返回{}条匹配记录", hits.length);

            // 提取标识信息
            for (SearchHit hit : hits) {
                Map<String, Object> sourceAsMap = hit.getSourceAsMap();
                if (sourceAsMap != null) {
                    Map<String, String> identifier = new HashMap<>();
                    identifier.put("sourceTable", getStringSafely(sourceAsMap, EsTwitterFields.SOURCE_TABLE));
                    identifier.put("sourceId", getStringSafely(sourceAsMap, EsTwitterFields.SOURCE_ID));

                    // 验证标识信息完整性
                    if (identifier.get("sourceTable") != null && identifier.get("sourceId") != null) {
                        results.add(identifier);
                        log.debug("添加匹配记录: sourceTable={}, sourceId={}",
                                identifier.get("sourceTable"), identifier.get("sourceId"));
                    } else {
                        log.warn("跳过不完整的记录: sourceTable={}, sourceId={}",
                                identifier.get("sourceTable"), identifier.get("sourceId"));
                    }
                }
            }

            log.info("ES查询完成，有效匹配记录数: {}", results.size());
            return results;

        } catch (Exception e) {
            log.error("执行ES查询失败: {}", e.getMessage(), e);
            return results;
        }
    }

    /**
     * 执行ES查询并返回标识信息（支持分页）
     *
     * @param boolQuery 布尔查询条件
     * @param from      起始位置
     * @param size      查询数量
     * @return 包含sourceTable和sourceId的结果列表
     */
    private List<Map<String, String>> executeEsSearchForIdentifiersWithPagination(BoolQueryBuilder boolQuery, int from, int size) {
        List<Map<String, String>> results = new ArrayList<>();

        try {
            // 创建ES搜索请求
            EsSearchRequest esSearchRequest = new EsSearchRequest();
            esSearchRequest.setBq(boolQuery);
            esSearchRequest.setFrom((long) from);
            esSearchRequest.setSize((long) size);
            esSearchRequest.setNeedScroll(false);

            // 添加排序规则，确保与分页查询一致
            esSearchRequest.setSortName(EsTwitterFields.FOLLOWERS);
            esSearchRequest.setSortOrder("desc");

            // 只查询必要的字段以提升性能
            String[] fields = {EsTwitterFields.SOURCE_TABLE, EsTwitterFields.SOURCE_ID};
            esSearchRequest.setFields(fields);

            log.debug("执行ES分页查询，条件: {}, from: {}, size: {}, sort: {}:{}", boolQuery.toString(), from, size,
                    EsTwitterFields.FOLLOWERS, "desc");

            // 执行查询
            SearchResponse searchResponse = EsRestClient.searchWithTermQuery(getEsIndexInfo(), esSearchRequest);

            if (searchResponse == null) {
                log.warn("ES分页查询返回null响应");
                return results;
            }

            SearchHits searchHits = searchResponse.getHits();
            if (searchHits == null || searchHits.getHits() == null) {
                log.warn("ES分页查询返回空结果");
                return results;
            }

            SearchHit[] hits = searchHits.getHits();
            log.info("ES分页查询返回{}条匹配记录", hits.length);

            // 提取标识信息
            for (SearchHit hit : hits) {
                Map<String, Object> sourceAsMap = hit.getSourceAsMap();
                if (sourceAsMap != null) {
                    Map<String, String> identifier = new HashMap<>();
                    identifier.put("sourceTable", getStringSafely(sourceAsMap, EsTwitterFields.SOURCE_TABLE));
                    identifier.put("sourceId", getStringSafely(sourceAsMap, EsTwitterFields.SOURCE_ID));

                    // 验证标识信息完整性
                    if (identifier.get("sourceTable") != null && identifier.get("sourceId") != null) {
                        results.add(identifier);
                    }
                }
            }

            log.info("ES分页查询完成，有效匹配记录数: {}", results.size());
            return results;

        } catch (Exception e) {
            log.error("执行ES分页查询失败: {}", e.getMessage(), e);
            return results;
        }
    }

    /**
     * 执行ES计数查询
     *
     * @param boolQuery 布尔查询条件
     * @return 匹配记录总数
     */
    private long executeEsCountQuery(BoolQueryBuilder boolQuery) {
        try {
            // 创建ES搜索请求（只查询计数）
            EsSearchRequest esSearchRequest = new EsSearchRequest();
            esSearchRequest.setBq(boolQuery);
            esSearchRequest.setFrom(0L);
            esSearchRequest.setSize(0L); // 只查询计数，不返回具体记录
            esSearchRequest.setNeedScroll(false);
            esSearchRequest.setTrackTotalHits(true);

            log.debug("执行ES计数查询，条件: {}", boolQuery.toString());

            // 执行查询
            SearchResponse searchResponse = EsRestClient.searchWithTermQuery(getEsIndexInfo(), esSearchRequest);

            if (searchResponse == null) {
                log.warn("ES计数查询返回null响应");
                return 0;
            }

            SearchHits searchHits = searchResponse.getHits();
            if (searchHits == null) {
                log.warn("ES计数查询返回空结果");
                return 0;
            }

            long totalCount = searchHits.getTotalHits().value;
            log.info("ES计数查询完成，匹配记录总数: {}", totalCount);

            return totalCount;

        } catch (Exception e) {
            log.error("执行ES计数查询失败: {}", e.getMessage(), e);
            return 0;
        }
    }

}
